package com.iagent.bean;

import com.iagent.constant.HttpConstant;
import com.iagent.constant.HttpEnum;
import com.iagent.request.HttpExecutor;
import com.iagent.request.RequestConfig;
import com.iagent.request.SimpleHttpExecutor;
import com.iagent.util.ClassUtils;
import com.iagent.util.StringUtils;

import java.io.Serializable;
import java.lang.reflect.Method;

/**
 * <p>http uri information loading to HttpUriBean object,
 * support deep clone and serializable,use to Builder Pattern to create object
 * </p>
 */
public class IagentBean implements Cloneable,Serializable {

    /**
     * http request url
     */
    private String url;

    /**
     * origin url, like ${user.url}/userManagement
     * @since 2.1.0
     */
    private String originUrl;

    /**
     * the RequestConfig will take the place of other attributes in next version
     *
     * @since 2.2.0
     */
    private RequestConfig requestConfig;

    /**
     * the attribute will take the place of the returnClass attributes in class IagentBeanWrapper
     *
     * @see IagentBeanWrapper
     * @since 2.2.0
     */
    private Class<?> returnClass;

    /**
     * Record executive method
     *
     * @since 2.2.1
     */
    private Method method;

    /**
     *
     * @param builder iagent bean builder
     */
    private IagentBean(IagentBeanBuilder builder) {
        super();
        this.url = builder.getUrl();
        this.originUrl = builder.getUrl();
        this.returnClass = builder.getReturnClass();
        RequestConfig config = new RequestConfig();
        config.setConnectionTime(builder.getConnectionTime());
        config.setContentType(builder.getContentType());
        config.setReadTime(builder.getReadTime());
        config.setRequestType(builder.getRequestType());
        config.setHttpExecutor(builder.getClazzHttpExecutor());
        this.requestConfig = config;
        this.method = builder.getMethod();
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public HttpEnum getRequestType() {
        return this.requestConfig.getRequestType();
    }

    public void setRequestType(HttpEnum requestType) {
        this.requestConfig.setRequestType(requestType);
    }

    public String getContentType() {
        return this.requestConfig.getContentType();
    }

    public void setContentType(String contentType) {
        this.requestConfig.setContentType(contentType);
    }

    public int getConnectionTime() {
        return this.requestConfig.getConnectionTime();
    }

    public void setConnectionTime(int connectionTime) {
        this.requestConfig.setConnectionTime(connectionTime);
    }

    public int getReadTime() {
        return this.requestConfig.getReadTime();
    }

    public void setReadTime(int readTime) {
        this.requestConfig.setReadTime(readTime);
    }

    public String getOriginUrl() {
        return originUrl;
    }

    public void setOriginUrl(String originUrl) {
        this.originUrl = originUrl;
    }

    public Class<? extends HttpExecutor> getClazzHttpExecutor() {
        return this.requestConfig.getHttpExecutor();
    }

    public void setClazzHttpExecutor(Class<? extends HttpExecutor> clazzHttpExecutor) {
        this.requestConfig.setHttpExecutor(clazzHttpExecutor);
    }

    public RequestConfig getRequestConfig() {
        return requestConfig;
    }

    public void setRequestConfig(RequestConfig requestConfig) {
        this.requestConfig = requestConfig;
    }

    public Class<?> getReturnClass() {
        return returnClass;
    }

    public void setReturnClass(Class<?> returnClass) {
        this.returnClass = returnClass;
    }

    public Method getMethod() {
        return method;
    }

    public void setMethod(Method method) {
        this.method = method;
    }

    @Override
    public IagentBean clone() throws CloneNotSupportedException {
        return (IagentBean) super.clone();
    }

    /**
     * <b>IagentBean Builder</b>
     */
    public static class IagentBeanBuilder{

        private String url;

        private HttpEnum requestType;

        private String contentType;

        private int connectionTime;

        private int readTime;

        private RequestConfig requestConfig;

        private Class<? extends HttpExecutor> clazzHttpExecutor;

        private Class<?> returnClass;

        private Method method;

        public IagentBeanBuilder(RequestConfig requestConfig){
            super();
            this.requestConfig = requestConfig;
        }

        public static IagentBeanBuilder create(RequestConfig requestConfig){
            return new IagentBeanBuilder(requestConfig);
        }

        public IagentBeanBuilder url(String url){
            this.url = url;
            return this;
        }

        public IagentBeanBuilder requestType(HttpEnum[] requestType){
            if (requestConfig != null && (requestType == null || requestType.length == 0)) {
                this.requestType = requestConfig.getRequestType();
            } else {
                this.requestType = requestType[0];
            }
            return this;
        }

        public IagentBeanBuilder contentType(String contentType){
            if (StringUtils.isEmpty(contentType) && requestConfig != null) {
                this.contentType = requestConfig.getContentType();
            } else {
                this.contentType = contentType;
            }
            return this;
        }

        public IagentBeanBuilder connectionTime(int connectionTime){
            if (connectionTime <= 0 && requestConfig != null) {
                this.connectionTime = requestConfig.getConnectionTime();
            } else {
                this.connectionTime = connectionTime;
            }
            return this;
        }

        public IagentBeanBuilder readTime(int readTime){
            if (readTime <= 0 && requestConfig != null) {
                this.readTime = requestConfig.getReadTime();
            } else {
                this.readTime = readTime;
            }
            return this;
        }

        public IagentBeanBuilder httpExecutor(Class<? extends HttpExecutor> clazzHttpExecutor){
            if (requestConfig != null && (clazzHttpExecutor == null || ClassUtils.isEqualsClass(HttpExecutor.DEFAULT_EXECUTOR, clazzHttpExecutor))) {
                this.clazzHttpExecutor = requestConfig.getHttpExecutor();
            } else {
                this.clazzHttpExecutor = clazzHttpExecutor;
            }
            return this;
        }

        public IagentBeanBuilder returnClass(Class<?> returnClass) {
            this.returnClass = returnClass;
            return this;
        }

        public IagentBeanBuilder method(Method method) {
            this.method = method;
            return this;
        }

        public String getUrl() {
            return url;
        }

        public HttpEnum getRequestType() {
            return requestType;
        }

        public String getContentType() {
            return contentType;
        }

        public int getConnectionTime() {
            return connectionTime;
        }

        public int getReadTime() {
            return readTime;
        }

        public Class<? extends HttpExecutor> getClazzHttpExecutor() {
            return clazzHttpExecutor;
        }

        public Class<?> getReturnClass() {
            return returnClass;
        }

        public Method getMethod() {
            return method;
        }

        public IagentBean build(){
            return new IagentBean(this);
        }

    }

}
